﻿using System;

namespace Samurai.Wakizashi.Workflow
{
    public interface IWorkflowStep<T> where T : class, IWorkflowContext 
    {
        /// <summary>
        /// Occurs when the workflow step is completed.
        /// </summary>
        event EventHandler<WorkflowStepCompletedEventArgs<T>> Completed;

        /// <summary>
        /// Occurs when the workflow step has failed execution.
        /// </summary>
        event EventHandler<WorkflowStepCompletedEventArgs<T>> Failed;

        /// <summary>
        /// Gets or sets the context that is shared among all steps in the workflow.
        /// </summary>
        /// <value>The context.</value>
        T Context { get; set; }

        /// <summary>
        /// Gets or sets the thread on which to execute this step.
        /// </summary>
        /// <value>The thread.</value>
        ThreadType Thread { get; set; }

        /// <summary>
        /// Gets or sets the workflow in which this step is to execute.
        /// </summary>
        /// <value>The workflow.</value>
        IWorkflow<T> Workflow { get; set; }

        /// <summary>
        /// Gets or sets the expression that dictates whether or not this step is to be executed.
        /// </summary>
        /// <remarks>The execution predicate is evaluated just before the step instance is to be executed.</remarks>
        /// <value>
        /// The execution predicate.
        /// </value>
        Predicate<T> ExecutionPredicate { get; set; }

        /// <summary>
        /// Gets the name of the step.
        /// </summary>
        /// <value>The name of the step.</value>
        string StepName { get; }

        /// <summary>
        /// Gets a value indicating whether this instance has completed.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance has completed; otherwise, <c>false</c>.
        /// </value>
        bool HasCompleted { get; }

        /// <summary>
        /// Gets or sets a value indicating whether this instance's execution is conditional.
        /// </summary>
        /// <remarks>This property simply checks to see if the <see cref="ExecutionPredicate"/> property is null. It returns false if it's null, true if it is not.</remarks>
        /// <value>
        /// 	<c>true</c> if this instance's execution is conditional; otherwise, <c>false</c>.
        /// </value>
        bool IsConditional { get; }

        /// <summary>
        /// Gets or sets a value indicating whether to halt workflow on the failure of this step.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if [halt workflow on failure]; otherwise, <c>false</c>.
        /// </value>
        bool IsCritical { get; set; }

        /// <summary>
        /// Executes the step.
        /// </summary>
        void ExecuteStep();

        /// <summary>
        /// Resets the completed flag.
        /// </summary>
        void ResetCompletedFlag();
    }
}
